package com.vhall.component.service.gift.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vhall.component.dao.gift.GiftMapper;
import com.vhall.component.entity.gift.dto.GiftDataDTO;
import com.vhall.component.entity.gift.dto.GiftListDataDTO;
import com.vhall.component.entity.gift.entity.Gift;
import com.vhall.component.entity.gift.enums.GiftSourceStatusEnum;
import com.vhall.component.entity.gift.enums.GiftSourceTypeEnum;
import com.vhall.component.entity.gift.vo.*;
import com.vhall.component.entity.page.vo.PageVO;
import com.vhall.component.entity.rbac.enums.RoleTypeEnum;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.StringUtils;
import com.vhall.component.plugin.common.enums.DeleteStatusEnum;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.service.gift.AdmGiftService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Preconditions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * AdmGiftServiceImpl-
 *
 * @author xing.wang
 * @date 2022/10/9
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdmGiftServiceImpl extends ServiceImpl<GiftMapper, Gift> implements AdmGiftService {
    private final GiftMapper mapper;

    @Value("${paas.apps.lite.appId}")
    public String appId;
    @Value("${paas.apps.lite.appSecret}")
    public String appSecret;

    @Override
    public GiftDataDTO create(GiftCreateVO vo) {

        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == null || RoleTypeEnum.DEPT_LEVEL.getValue().equals(token.getRoleType())) {
            return new GiftDataDTO();
        }

        checkGiftNameRepeat(0L, vo.getName());
        // 获取当前表情最大序号
        int maxGiftSort = getMaxGiftSort();
        Gift gift = new Gift();
        BeanUtil.copyProperties(vo, gift);
        LocalDateTime now = LocalDateTime.now();
        gift.setCreatedAt(now);
        gift.setUpdatedAt(now);
        gift.setCreatorId(token.getAccountId().toString());
        gift.setSourceStatus(GiftSourceStatusEnum.USER_ADD.getStatus());
        gift.setSourceType(GiftSourceTypeEnum.WEB.getType());
        gift.setCreatorNickname(token.getNickname());
        gift.setAppId(appId);
        gift.setPrice(new BigDecimal("0"));
        gift.setGiftSort(maxGiftSort);
        mapper.insert(gift);
        GiftDataDTO dto = new GiftDataDTO();
        BeanUtil.copyProperties(gift, dto);
        return dto;
    }

    private int getMaxGiftSort() {

        LambdaQueryWrapper<Gift> where2 = Wrappers.lambdaQuery();
        where2.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        Integer count = mapper.selectCount(where2);
        Preconditions.checkArgument(count <= 30, "当前表情数量超过限制！");

        LambdaQueryWrapper<Gift> where = Wrappers.lambdaQuery();
        where.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        where.last("ORDER BY gift_sort desc limit 1");
        Gift gift = mapper.selectOne(where);


        return gift == null ? 1 : gift.getGiftSort() + 1;


    }


    @Override
    public Boolean update(GiftUpdateVO vo) {
        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == null || RoleTypeEnum.DEPT_LEVEL.getValue().equals(token.getRoleType())) {
            return false;
        }
        checkGiftNameRepeat(vo.getId(), vo.getName());
        Gift gift = new Gift();
        BeanUtil.copyProperties(vo, gift);
        LocalDateTime now = LocalDateTime.now();
        gift.setUpdatedAt(now);
        return updateById(gift);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(GiftDeleteVO vo) {
        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == null || RoleTypeEnum.DEPT_LEVEL.getValue().equals(token.getRoleType())) {
            return false;
        }

        Gift giftEntity = mapper.selectById(vo.getId());

        LambdaQueryWrapper<Gift> whereCount = Wrappers.lambdaQuery();
        whereCount.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        Integer count = mapper.selectCount(whereCount);

        Gift gift = new Gift();
        gift.setId(vo.getId());
        LocalDateTime now = LocalDateTime.now();
        gift.setDeletedAt(now);
        gift.setDeleted(DeleteStatusEnum.DELETE.getStatus());
        updateById(gift);

        // 4、更新其他sort值。--比当前sort小的数据不需要更新sort，比他大的减1.
        if (count > giftEntity.getGiftSort()) {
            LambdaUpdateWrapper<Gift> updateBatchBind = Wrappers.lambdaUpdate();
            updateBatchBind.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
            updateBatchBind.between(Gift::getGiftSort, giftEntity.getGiftSort() + 1, count + 1);
            updateBatchBind.setSql("gift_sort = gift_sort-1");
            baseMapper.update(null, updateBatchBind);
        }

        return true;
    }

    @Override
    public PageVO<GiftListDataDTO> list(GiftListVO vo) {
        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == null || RoleTypeEnum.DEPT_LEVEL.getValue().equals(token.getRoleType())) {
            return new PageVO<>();
        }

        LambdaQueryWrapper<Gift> where = Wrappers.lambdaQuery();
        where.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus()).eq(Gift::getAppId, appId);
        where.like(StringUtils.isNotEmpty(vo.getKeyword()), Gift::getName, vo.getKeyword());
        where.last("ORDER BY gift_sort asc ,id asc");
        Integer pageIndex = vo.getPage();
        Integer pageSize = vo.getPageSize();
        Page<Gift> page = new Page<>(pageIndex, pageSize);
        Page<Gift> quickRepliesEntityPage = mapper.selectPage(page, where);
        List<GiftListDataDTO> list = new ArrayList<>();
        if (Objects.nonNull(quickRepliesEntityPage) && quickRepliesEntityPage.getTotal() > 0) {
            list = quickRepliesEntityPage.getRecords().stream().map(entity -> {
                GiftListDataDTO dto = new GiftListDataDTO();
                BeanUtil.copyProperties(entity, dto, false);
                return dto;
            }).collect(Collectors.toList());
        }
        return new PageVO<>(pageIndex, pageSize, (int) page.getTotal(), list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean giftSort(GiftSortVO vo) {


        Integer newSort = vo.getGiftSort();
        Gift gift = mapper.selectById(vo.getId());
        Preconditions.checkArgument(gift != null, "表情id传入有误！");
        Integer oldSort = gift.getGiftSort();
        if (oldSort.equals(newSort)) {
            throw new BusinessException(BizErrorCode.BIZ_REPEAT_SERIAL_NUMBER);
        }

        LambdaQueryWrapper<Gift> whereCount = Wrappers.lambdaQuery();
        whereCount.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        Integer count = mapper.selectCount(whereCount);
        Preconditions.checkArgument(newSort <= count, "不能大于创建的表情数！");

        // 3、执行更新操作。分为两步，第一步：将新老两个值之间的数据修改。然后就是修改当前绑定信息。
        // 大变小，中间值增大1。小变大，中间值减1。
        LambdaUpdateWrapper<Gift> updateBatchBind = Wrappers.lambdaUpdate();
        updateBatchBind.eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        if (newSort > oldSort) {
            updateBatchBind.between(Gift::getGiftSort, oldSort, newSort);
            updateBatchBind.setSql("gift_sort = gift_sort-1");
        } else {
            updateBatchBind.between(Gift::getGiftSort, newSort, oldSort);
            updateBatchBind.setSql("gift_sort = gift_sort+1");
        }
        mapper.update(null, updateBatchBind);
        // 更新当前数据的sort.
        LambdaUpdateWrapper<Gift> updateCurrent = Wrappers.lambdaUpdate();
        updateCurrent.eq(Gift::getId, vo.getId());
        updateCurrent.set(Gift::getGiftSort, newSort);
        mapper.update(null, updateCurrent);
        return true;
    }

    /**
     * 检查表情名称是否有重复
     *
     * @param id   表情id
     * @param name 表情名称
     */
    private void checkGiftNameRepeat(Long id, String name) {
        LambdaQueryWrapper<Gift> where = Wrappers.lambdaQuery();
        where.eq(Gift::getName, name).ne(Gift::getId, id).eq(Gift::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        Integer giftCount = mapper.selectCount(where);
        if (giftCount > 0) {
            throw new BusinessException(BizErrorCode.COMP_GIFT_ERR_NAME_REPEAT);
        }
    }


}
